package logger

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"

	"kwdb-import/pkg/errors"
)

// LogLevel 日志级别
type LogLevel int

const (
	DebugLevel LogLevel = iota
	InfoLevel
	WarnLevel
	ErrorLevel
	FatalLevel
)

// String 返回日志级别的字符串表示
func (l LogLevel) String() string {
	switch l {
	case DebugLevel:
		return "DEBUG"
	case InfoLevel:
		return "INFO"
	case WarnLevel:
			return "WARN"
	case ErrorLevel:
		return "ERROR"
	case FatalLevel:
		return "FATAL"
	default:
		return "UNKNOWN"
	}
}

// ParseLogLevel 解析日志级别字符串
func ParseLogLevel(level string) (LogLevel, error) {
	switch strings.ToUpper(level) {
	case "DEBUG":
		return DebugLevel, nil
	case "INFO":
		return InfoLevel, nil
	case "WARN", "WARNING":
		return WarnLevel, nil
	case "ERROR":
		return ErrorLevel, nil
	case "FATAL":
		return FatalLevel, nil
	default:
		return InfoLevel, fmt.Errorf("invalid log level: %s", level)
	}
}

// LogFormat 日志格式
type LogFormat int

const (
	TextFormat LogFormat = iota
	JSONFormat
)

// LogEntry 日志条目
type LogEntry struct {
	Timestamp time.Time            `json:"timestamp"`
	Level     LogLevel             `json:"level"`
	Message   string               `json:"message"`
	Fields    map[string]interface{} `json:"fields,omitempty"`
	Caller    string               `json:"caller,omitempty"`
	Error     string               `json:"error,omitempty"`
	TraceID   string               `json:"trace_id,omitempty"`
	SpanID    string               `json:"span_id,omitempty"`
}

// Logger 日志记录器接口
type Logger interface {
	Debug(msg string, fields ...Field)
	Info(msg string, fields ...Field)
	Warn(msg string, fields ...Field)
	Error(msg string, fields ...Field)
	Fatal(msg string, fields ...Field)
	
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
	
	WithField(key string, value interface{}) Logger
	WithFields(fields map[string]interface{}) Logger
	WithError(err error) Logger
	WithContext(ctx context.Context) Logger
	
	SetLevel(level LogLevel)
	GetLevel() LogLevel
	Close() error
}

// Field 日志字段
type Field struct {
	Key   string
	Value interface{}
}

// NewField 创建新的日志字段
func NewField(key string, value interface{}) Field {
	return Field{Key: key, Value: value}
}

// String 字符串字段
func String(key, value string) Field {
	return Field{Key: key, Value: value}
}

// Int 整数字段
func Int(key string, value int) Field {
	return Field{Key: key, Value: value}
}

// Int64 64位整数字段
func Int64(key string, value int64) Field {
	return Field{Key: key, Value: value}
}

// Float64 浮点数字段
func Float64(key string, value float64) Field {
	return Field{Key: key, Value: value}
}

// Bool 布尔字段
func Bool(key string, value bool) Field {
	return Field{Key: key, Value: value}
}

// Duration 时间间隔字段
func Duration(key string, value time.Duration) Field {
	return Field{Key: key, Value: value.String()}
}

// Time 时间字段
func Time(key string, value time.Time) Field {
	return Field{Key: key, Value: value.Format(time.RFC3339)}
}

// ErrorField 错误字段
func ErrorField(err error) Field {
	return Field{Key: "error", Value: err.Error()}
}

// KWDBLogger 具体的日志记录器实现
type KWDBLogger struct {
	mu       sync.RWMutex
	level    LogLevel
	format   LogFormat
	writer   io.Writer
	fields   map[string]interface{}
	caller   bool
	traceID  string
	spanID   string
	filePath string
	file     *os.File
}

// Config 日志配置
type Config struct {
	Level      LogLevel  `json:"level"`
	Format     LogFormat `json:"format"`
	Output     string    `json:"output"` // "stdout", "stderr", or file path
	Caller     bool      `json:"caller"`
	MaxSize    int64     `json:"max_size"`    // 最大文件大小（字节）
	MaxBackups int       `json:"max_backups"` // 最大备份文件数
	MaxAge     int       `json:"max_age"`     // 最大保留天数
	Compress   bool      `json:"compress"`    // 是否压缩备份文件
}

// DefaultConfig 默认配置
func DefaultConfig() *Config {
	return &Config{
		Level:      InfoLevel,
		Format:     TextFormat,
		Output:     "stdout",
		Caller:     true,
		MaxSize:    100 * 1024 * 1024, // 100MB
		MaxBackups: 5,
		MaxAge:     30,
		Compress:   true,
	}
}

// NewLogger 创建新的日志记录器
func NewLogger(config *Config) (Logger, error) {
	if config == nil {
		config = DefaultConfig()
	}
	
	logger := &KWDBLogger{
		level:  config.Level,
		format: config.Format,
		fields: make(map[string]interface{}),
		caller: config.Caller,
	}
	
	// 设置输出
	if err := logger.setOutput(config.Output); err != nil {
		return nil, err
	}
	
	return logger, nil
}

// setOutput 设置输出目标
func (l *KWDBLogger) setOutput(output string) error {
    // 当未配置或为空时，默认输出到 stdout
    if strings.TrimSpace(output) == "" {
        l.writer = os.Stdout
        return nil
    }
    switch output {
    case "stdout":
        l.writer = os.Stdout
    case "stderr":
        l.writer = os.Stderr
    default:
        // 文件输出
        dir := filepath.Dir(output)
        if err := os.MkdirAll(dir, 0755); err != nil {
            return fmt.Errorf("failed to create log directory: %w", err)
        }

        // 以可读写方式打开，便于在新文件开头写入 UTF-8 BOM
        file, err := os.OpenFile(output, os.O_CREATE|os.O_RDWR, 0644)
        if err != nil {
            return fmt.Errorf("failed to open log file: %w", err)
        }

        // 如果是新文件或空文件，写入 UTF-8 BOM，帮助 Windows 记事本正确识别编码
        if fi, statErr := file.Stat(); statErr == nil {
            if fi.Size() == 0 {
                // UTF-8 BOM: 0xEF 0xBB 0xBF
                _, _ = file.Write([]byte{0xEF, 0xBB, 0xBF})
            }
        }

        // 定位到末尾，后续日志采用追加写入语义
        _, _ = file.Seek(0, io.SeekEnd)

        l.file = file
        l.writer = file
        l.filePath = output
    }

    return nil
}

// log 记录日志
func (l *KWDBLogger) log(level LogLevel, msg string, fields ...Field) {
	l.mu.RLock()
	currentLevel := l.level
	l.mu.RUnlock()
	
	if level < currentLevel {
		return
	}
	
	entry := LogEntry{
		Timestamp: time.Now(),
		Level:     level,
		Message:   msg,
		Fields:    make(map[string]interface{}),
		TraceID:   l.traceID,
		SpanID:    l.spanID,
	}
	
	// 添加全局字段
	l.mu.RLock()
	for k, v := range l.fields {
		entry.Fields[k] = v
	}
	l.mu.RUnlock()
	
	// 添加当前字段
	for _, field := range fields {
		entry.Fields[field.Key] = field.Value
	}
	
	// 添加调用者信息
	if l.caller {
		if caller := getCaller(3); caller != "" {
			entry.Caller = caller
		}
	}
	
	// 格式化并输出
	l.writeEntry(entry)
	
	// 如果是Fatal级别，退出程序
	if level == FatalLevel {
		os.Exit(1)
	}
}

// writeEntry 写入日志条目
func (l *KWDBLogger) writeEntry(entry LogEntry) {
	l.mu.Lock()
	defer l.mu.Unlock()
	
	var output string
	
	switch l.format {
	case JSONFormat:
		data, _ := json.Marshal(entry)
		output = string(data) + "\n"
	default:
		output = l.formatText(entry)
	}
	
	l.writer.Write([]byte(output))
}

// formatText 格式化文本日志
func (l *KWDBLogger) formatText(entry LogEntry) string {
	var parts []string
	
	// 时间戳
	parts = append(parts, entry.Timestamp.Format("2006-01-02 15:04:05.000"))
	
	// 级别
	parts = append(parts, fmt.Sprintf("[%s]", entry.Level.String()))
	
	// 调用者
	if entry.Caller != "" {
		parts = append(parts, fmt.Sprintf("[%s]", entry.Caller))
	}
	
	// 追踪ID
	if entry.TraceID != "" {
		parts = append(parts, fmt.Sprintf("[trace:%s]", entry.TraceID))
	}
	
	// 消息
	parts = append(parts, entry.Message)
	
	// 字段
	if len(entry.Fields) > 0 {
		fieldParts := make([]string, 0, len(entry.Fields))
		for k, v := range entry.Fields {
			fieldParts = append(fieldParts, fmt.Sprintf("%s=%v", k, v))
		}
		parts = append(parts, fmt.Sprintf("[%s]", strings.Join(fieldParts, ", ")))
	}
	
	// 错误
	if entry.Error != "" {
		parts = append(parts, fmt.Sprintf("error=%s", entry.Error))
	}
	
	return strings.Join(parts, " ") + "\n"
}

// getCaller 获取调用者信息
func getCaller(skip int) string {
	_, file, line, ok := runtime.Caller(skip)
	if !ok {
		return ""
	}
	
	return fmt.Sprintf("%s:%d", filepath.Base(file), line)
}

// Debug 记录调试日志
func (l *KWDBLogger) Debug(msg string, fields ...Field) {
	l.log(DebugLevel, msg, fields...)
}

// Info 记录信息日志
func (l *KWDBLogger) Info(msg string, fields ...Field) {
	l.log(InfoLevel, msg, fields...)
}

// Warn 记录警告日志
func (l *KWDBLogger) Warn(msg string, fields ...Field) {
	l.log(WarnLevel, msg, fields...)
}

// Error 记录错误日志
func (l *KWDBLogger) Error(msg string, fields ...Field) {
	l.log(ErrorLevel, msg, fields...)
}

// Fatal 记录致命错误日志
func (l *KWDBLogger) Fatal(msg string, fields ...Field) {
	l.log(FatalLevel, msg, fields...)
}

// Debugf 格式化调试日志
func (l *KWDBLogger) Debugf(format string, args ...interface{}) {
	l.log(DebugLevel, fmt.Sprintf(format, args...))
}

// Infof 格式化信息日志
func (l *KWDBLogger) Infof(format string, args ...interface{}) {
	l.log(InfoLevel, fmt.Sprintf(format, args...))
}

// Warnf 格式化警告日志
func (l *KWDBLogger) Warnf(format string, args ...interface{}) {
	l.log(WarnLevel, fmt.Sprintf(format, args...))
}

// Errorf 格式化错误日志
func (l *KWDBLogger) Errorf(format string, args ...interface{}) {
	l.log(ErrorLevel, fmt.Sprintf(format, args...))
}

// Fatalf 格式化致命错误日志
func (l *KWDBLogger) Fatalf(format string, args ...interface{}) {
	l.log(FatalLevel, fmt.Sprintf(format, args...))
}

// WithField 添加字段
func (l *KWDBLogger) WithField(key string, value interface{}) Logger {
	newLogger := l.clone()
	newLogger.fields[key] = value
	return newLogger
}

// WithFields 添加多个字段
func (l *KWDBLogger) WithFields(fields map[string]interface{}) Logger {
	newLogger := l.clone()
	for k, v := range fields {
		newLogger.fields[k] = v
	}
	return newLogger
}

// WithError 添加错误字段
func (l *KWDBLogger) WithError(err error) Logger {
	newLogger := l.clone()
	
	if kwdbErr, ok := err.(*errors.KWDBError); ok {
		// 处理KWDBError
		newLogger.fields["error"] = kwdbErr.Error()
		newLogger.fields["error_type"] = string(kwdbErr.Type)
		newLogger.fields["error_severity"] = string(kwdbErr.GetSeverity())
		newLogger.fields["error_code"] = kwdbErr.ErrorCode
		
		// 添加上下文信息
		for k, v := range kwdbErr.GetContext() {
			newLogger.fields[fmt.Sprintf("error_ctx_%s", k)] = v
		}
		
		if kwdbErr.GetSuggestion() != "" {
			newLogger.fields["error_suggestion"] = kwdbErr.GetSuggestion()
		}
	} else {
		// 处理标准错误
		newLogger.fields["error"] = err.Error()
	}
	
	return newLogger
}

// WithContext 从上下文添加追踪信息
func (l *KWDBLogger) WithContext(ctx context.Context) Logger {
	newLogger := l.clone()
	
	// 尝试从上下文获取追踪ID
	if traceID := ctx.Value("trace_id"); traceID != nil {
		if id, ok := traceID.(string); ok {
			newLogger.traceID = id
		}
	}
	
	// 尝试从上下文获取Span ID
	if spanID := ctx.Value("span_id"); spanID != nil {
		if id, ok := spanID.(string); ok {
			newLogger.spanID = id
		}
	}
	
	return newLogger
}

// SetLevel 设置日志级别
func (l *KWDBLogger) SetLevel(level LogLevel) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.level = level
}

// GetLevel 获取日志级别
func (l *KWDBLogger) GetLevel() LogLevel {
	l.mu.RLock()
	defer l.mu.RUnlock()
	return l.level
}

// Close 关闭日志记录器
func (l *KWDBLogger) Close() error {
	l.mu.Lock()
	defer l.mu.Unlock()
	
	if l.file != nil {
		return l.file.Close()
	}
	return nil
}

// clone 克隆日志记录器
func (l *KWDBLogger) clone() *KWDBLogger {
	l.mu.RLock()
	defer l.mu.RUnlock()
	
	newFields := make(map[string]interface{})
	for k, v := range l.fields {
		newFields[k] = v
	}
	
	return &KWDBLogger{
		level:    l.level,
		format:   l.format,
		writer:   l.writer,
		fields:   newFields,
		caller:   l.caller,
		traceID:  l.traceID,
		spanID:   l.spanID,
		filePath: l.filePath,
		file:     l.file,
	}
}

// 全局日志记录器
var (
	globalLogger Logger
	globalMu     sync.RWMutex
)

// init 初始化全局日志记录器
func init() {
	logger, _ := NewLogger(DefaultConfig())
	globalLogger = logger
}

// SetGlobalLogger 设置全局日志记录器
func SetGlobalLogger(logger Logger) {
	globalMu.Lock()
	defer globalMu.Unlock()
	globalLogger = logger
}

// GetGlobalLogger 获取全局日志记录器
func GetGlobalLogger() Logger {
	globalMu.RLock()
	defer globalMu.RUnlock()
	return globalLogger
}

// 全局日志函数

// Debug 全局调试日志
func Debug(msg string, fields ...Field) {
	GetGlobalLogger().Debug(msg, fields...)
}

// Info 全局信息日志
func Info(msg string, fields ...Field) {
	GetGlobalLogger().Info(msg, fields...)
}

// Warn 全局警告日志
func Warn(msg string, fields ...Field) {
	GetGlobalLogger().Warn(msg, fields...)
}

// Error 全局错误日志
func Error(msg string, fields ...Field) {
	GetGlobalLogger().Error(msg, fields...)
}

// Fatal 全局致命错误日志
func Fatal(msg string, fields ...Field) {
	GetGlobalLogger().Fatal(msg, fields...)
}

// Debugf 全局格式化调试日志
func Debugf(format string, args ...interface{}) {
	GetGlobalLogger().Debugf(format, args...)
}

// Infof 全局格式化信息日志
func Infof(format string, args ...interface{}) {
	GetGlobalLogger().Infof(format, args...)
}

// Warnf 全局格式化警告日志
func Warnf(format string, args ...interface{}) {
	GetGlobalLogger().Warnf(format, args...)
}

// Errorf 全局格式化错误日志
func Errorf(format string, args ...interface{}) {
	GetGlobalLogger().Errorf(format, args...)
}

// Fatalf 全局格式化致命错误日志
func Fatalf(format string, args ...interface{}) {
	GetGlobalLogger().Fatalf(format, args...)
}

// WithField 全局添加字段
func WithField(key string, value interface{}) Logger {
	return GetGlobalLogger().WithField(key, value)
}

// WithFields 全局添加多个字段
func WithFields(fields map[string]interface{}) Logger {
	return GetGlobalLogger().WithFields(fields)
}

// WithError 全局添加错误字段
func WithError(err error) Logger {
	return GetGlobalLogger().WithError(err)
}

// WithContext 全局从上下文添加追踪信息
func WithContext(ctx context.Context) Logger {
	return GetGlobalLogger().WithContext(ctx)
}

// SetLevel 设置全局日志级别
func SetLevel(level LogLevel) {
	GetGlobalLogger().SetLevel(level)
}

// GetLevel 获取全局日志级别
func GetLevel() LogLevel {
	return GetGlobalLogger().GetLevel()
}